package socket;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * 聊天室客户端
 */
public class Client {
    /*
        java.net.Socket 套接字     想象成电话.
        Socket封装了TCP协议的通讯细节,使得我们可以用它与服务端建立TCP连接.并通过它获取
        两个流(一个输入,一个输出),并基于这两个流的读写字节操作完成与远端(服务端)计算机的
        通讯.
     */
    private Socket socket;
    /**
     * 构造方法,用于初始化客户端
     */
    public Client(){
        try {
            /*
                实例化Socket时常用的构造方法需要我们传入两个参数
                参数1:远端计算机的IP地址信息
                参数2:远端计算机开启的服务端口
                对于客户端来说,远端就是服务端
                通过IP可以找到网络上的服务端计算机,通过端口连接到该机器上运行
                的服务端应用程序(这个端口就是该程序在服务端计算机上申请并打开的)
                本机:localhost    漏沟厚实的
             */
            System.out.println("正在连接服务端-----");
            socket = new Socket("localhost",8088);//连接的过程,连接好了才能实例化成功,连接不了报错
            //socket = new Socket("176.125.11.40",8088);//连接的过程,连接好了才能实例化成功,连接不了报错
            System.out.println("与服务端建立连接!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 客户端开始工作的方法
     */
    public void start(){
        try {
            //首先启动用于读取服务端发送过来消息的线程
            ServerHandler handler = new ServerHandler();
            Thread t = new Thread(handler);
            t.start();



            /*
                Socket提供的方法:
                OutputStream getOutputStream()
                通过该方法获取一个字节输出流,使用这个字节输出流写出的字节会发生给远端计算机.

                 */
            OutputStream out = socket.getOutputStream();
             /*
            转换输出流,高级流
            作用:
            1:负责在流链接中衔接字节流与字符流
            2:负责将写出的字符转换为字节
         */
            OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8");
             /*
            缓冲字符输出流,高级流
            作用:
            快写文本数据,提高写出效率
         */
            BufferedWriter bw = new BufferedWriter(osw);
             /*
            具有自动行刷新的缓冲字符输出流,高级流
            作用:
            1:按行写出文本数据
            2:自动的行刷新
         */
            PrintWriter pw = new PrintWriter(bw,true);

            Scanner sc = new Scanner(System.in);
            System.out.println("请输入文本内容,单独输入exit时退出");
            while (true){
                String line = sc.nextLine();
                if ("exit".equalsIgnoreCase(line)){
                    break;
                }
                pw.println(line);
            }

            System.out.println("连接完毕!");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                /*
                通讯完毕最终要关闭socket.
                 该方法会给远程计算机发送TCP断开信号,通知远程计算机
                 要断开TCP链接.
                */
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        Client client = new Client();
        client.start();
    }

    /**
     * 该线程用来循环读取服务端发送过来的信息
     */
    private class ServerHandler implements Runnable{
        public void run(){
            try {
                InputStream is = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(is,"UTF-8");
                BufferedReader br = new BufferedReader(isr);
                String line;
                while ((line = br.readLine()) != null) {
                    System.out.println( line);
                }
            }catch (IOException e){

            }
        }
    }
}

